5 * Copyright (c) 2002-2009, Sebastian Bergmann <sb@sebastian-bergmann.de>.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
12 * * Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
15 * * Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in
17 * the documentation and/or other materials provided with the
20 * * Neither the name of Sebastian Bergmann nor the names of his
21 * contributors may be used to endorse or promote products derived
22 * from this software without specific prior written permission.
24 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
25 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
26 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
27 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
28 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
29 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
30 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
31 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
32 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
33 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
34 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
35 * POSSIBILITY OF SUCH DAMAGE.
39 * @author Sebastian Bergmann <sb@sebastian-bergmann.de>
40 * @copyright 2002-2009 Sebastian Bergmann <sb@sebastian-bergmann.de>
41 * @license http://www.opensource.org/licenses/bsd-license.php BSD License
43 * @link http://www.phpunit.de/
44 * @since File available since Release 2.0.0
47 require_once 'PHPUnit/Framework.php';
48 require_once 'PHPUnit/Util/Filter.php';
49 require_once 'PHPUnit/Util/Printer.php';
50 require_once 'PHPUnit/Util/Test.php';
52 PHPUnit_Util_Filter::addFileToFilter(__FILE__, 'PHPUNIT');
55 * Prints the result of a TextUI TestRunner run.
59 * @author Sebastian Bergmann <sb@sebastian-bergmann.de>
60 * @copyright 2002-2009 Sebastian Bergmann <sb@sebastian-bergmann.de>
61 * @license http://www.opensource.org/licenses/bsd-license.php BSD License
62 * @version Release: 3.3.17
63 * @link http://www.phpunit.de/
64 * @since Class available since Release 2.0.0
66 class PHPUnit_TextUI_ResultPrinter extends PHPUnit_Util_Printer implements PHPUnit_Framework_TestListener
68 const EVENT_TEST_START = 0;
69 const EVENT_TEST_END = 1;
70 const EVENT_TESTSUITE_START = 2;
71 const EVENT_TESTSUITE_END = 3;
76 protected $column = 0;
81 protected $numberOfTests = array();
86 protected $testSuiteSize = array();
91 protected $lastEvent = -1;
96 protected $lastTestFailed = FALSE;
101 protected $colors = FALSE;
106 protected $debug = FALSE;
111 protected $verbose = FALSE;
116 protected $numAssertions = 0;
122 * @param boolean $verbose
123 * @param boolean $colors
124 * @param boolean $debug
125 * @throws InvalidArgumentException
126 * @since Method available since Release 3.0.0
128 public function __construct($out = NULL, $verbose = FALSE, $colors = FALSE, $debug = FALSE)
130 parent::__construct($out);
132 if (is_bool($colors)) {
133 $this->colors = $colors;
135 throw new InvalidArgumentException;
138 if (is_bool($debug)) {
139 $this->debug = $debug;
141 throw new InvalidArgumentException;
144 if (is_bool($verbose)) {
145 $this->verbose = $verbose;
147 throw new InvalidArgumentException;
152 * @param PHPUnit_Framework_TestResult $result
154 public function printResult(PHPUnit_Framework_TestResult $result)
156 $this->printHeader($result->time());
158 if ($result->errorCount() > 0) {
159 $this->printErrors($result);
162 if ($result->failureCount() > 0) {
163 if ($result->errorCount() > 0) {
167 $this->printFailures($result);
170 if ($this->verbose) {
171 if ($result->notImplementedCount() > 0) {
172 if ($result->failureCount() > 0) {
176 $this->printIncompletes($result);
179 if ($result->skippedCount() > 0) {
180 if ($result->notImplementedCount() > 0) {
184 $this->printSkipped($result);
188 $this->printFooter($result);
192 * @param array $defects
193 * @param integer $count
194 * @param string $type
196 protected function printDefects(array $defects, $count, $type)
198 static $called = FALSE;
206 "%sThere %s %d %s%s:\n",
209 ($count == 1) ? 'was' : 'were',
212 ($count == 1) ? '' : 's'
218 foreach ($defects as $defect) {
219 $this->printDefect($defect, $i++);
226 * @param PHPUnit_Framework_TestFailure $defect
227 * @param integer $count
229 protected function printDefect(PHPUnit_Framework_TestFailure $defect, $count)
231 $this->printDefectHeader($defect, $count);
232 $this->printDefectTrace($defect);
236 * @param PHPUnit_Framework_TestFailure $defect
237 * @param integer $count
239 protected function printDefectHeader(PHPUnit_Framework_TestFailure $defect, $count)
241 $failedTest = $defect->failedTest();
243 if ($failedTest instanceof PHPUnit_Framework_SelfDescribing) {
244 $testName = $failedTest->toString();
246 $testName = get_class($failedTest);
260 * @param PHPUnit_Framework_TestFailure $defect
262 protected function printDefectTrace(PHPUnit_Framework_TestFailure $defect)
265 $defect->toStringVerbose($this->verbose) .
266 PHPUnit_Util_Filter::getFilteredStacktrace(
267 $defect->thrownException(),
274 * @param PHPUnit_Framework_TestResult $result
276 protected function printErrors(PHPUnit_Framework_TestResult $result)
278 $this->printDefects($result->errors(), $result->errorCount(), 'error');
282 * @param PHPUnit_Framework_TestResult $result
284 protected function printFailures(PHPUnit_Framework_TestResult $result)
286 $this->printDefects($result->failures(), $result->failureCount(), 'failure');
290 * @param PHPUnit_Framework_TestResult $result
292 protected function printIncompletes(PHPUnit_Framework_TestResult $result)
294 $this->printDefects($result->notImplemented(), $result->notImplementedCount(), 'incomplete test');
298 * @param PHPUnit_Framework_TestResult $result
299 * @since Method available since Release 3.0.0
301 protected function printSkipped(PHPUnit_Framework_TestResult $result)
303 $this->printDefects($result->skipped(), $result->skippedCount(), 'skipped test');
307 * @param float $timeElapsed
309 protected function printHeader($timeElapsed)
314 $this->verbose ? "\n" : "\n\n",
315 PHPUnit_Util_Timer::secondsToTimeString($timeElapsed)
321 * @param PHPUnit_Framework_TestResult $result
323 protected function printFooter(PHPUnit_Framework_TestResult $result)
325 if ($result->wasSuccessful() &&
326 $result->allCompletlyImplemented() &&
327 $result->noneSkipped()) {
329 $this->write("\x1b[30;42m\x1b[2K");
334 "OK (%d test%s, %d assertion%s)\n",
337 (count($result) == 1) ? '' : 's',
338 $this->numAssertions,
339 ($this->numAssertions == 1) ? '' : 's'
344 $this->write("\x1b[0m\x1b[2K");
348 else if ((!$result->allCompletlyImplemented() ||
349 !$result->noneSkipped())&&
350 $result->wasSuccessful()) {
352 $this->write("\x1b[30;43m\x1b[2KOK, but incomplete or skipped tests!\n\x1b[0m\x1b[30;43m\x1b[2K");
354 $this->write("OK, but incomplete or skipped tests!\n");
359 "Tests: %d, Assertions: %d%s%s.\n",
362 $this->numAssertions,
363 $this->getCountString($result->notImplementedCount(), 'Incomplete'),
364 $this->getCountString($result->skippedCount(), 'Skipped')
369 $this->write("\x1b[0m\x1b[2K");
377 $this->write("\x1b[37;41m\x1b[2KFAILURES!\n\x1b[0m\x1b[37;41m\x1b[2K");
379 $this->write("FAILURES!\n");
384 "Tests: %d, Assertions: %s%s%s%s%s.\n",
387 $this->numAssertions,
388 $this->getCountString($result->failureCount(), 'Failures'),
389 $this->getCountString($result->errorCount(), 'Errors'),
390 $this->getCountString($result->notImplementedCount(), 'Incomplete'),
391 $this->getCountString($result->skippedCount(), 'Skipped')
396 $this->write("\x1b[0m\x1b[2K");
402 * @param integer $count
403 * @param string $name
405 * @since Method available since Release 3.0.0
407 protected function getCountString($count, $name)
425 public function printWaitPrompt()
427 $this->write("\n<RETURN> to continue\n");
433 * @param PHPUnit_Framework_Test $test
434 * @param Exception $e
437 public function addError(PHPUnit_Framework_Test $test, Exception $e, $time)
439 $this->writeProgress('E');
440 $this->lastTestFailed = TRUE;
444 * A failure occurred.
446 * @param PHPUnit_Framework_Test $test
447 * @param PHPUnit_Framework_AssertionFailedError $e
450 public function addFailure(PHPUnit_Framework_Test $test, PHPUnit_Framework_AssertionFailedError $e, $time)
452 $this->writeProgress('F');
453 $this->lastTestFailed = TRUE;
459 * @param PHPUnit_Framework_Test $test
460 * @param Exception $e
463 public function addIncompleteTest(PHPUnit_Framework_Test $test, Exception $e, $time)
465 $this->writeProgress('I');
466 $this->lastTestFailed = TRUE;
472 * @param PHPUnit_Framework_Test $test
473 * @param Exception $e
475 * @since Method available since Release 3.0.0
477 public function addSkippedTest(PHPUnit_Framework_Test $test, Exception $e, $time)
479 $this->writeProgress('S');
480 $this->lastTestFailed = TRUE;
484 * A testsuite started.
486 * @param PHPUnit_Framework_TestSuite $suite
487 * @since Method available since Release 2.2.0
489 public function startTestSuite(PHPUnit_Framework_TestSuite $suite)
491 if ($this->verbose) {
492 $name = $suite->getName();
495 $name = 'Test Suite';
502 $this->lastEvent == self::EVENT_TESTSUITE_END ? "\n" : '',
503 str_repeat(' ', count($this->testSuiteSize)),
509 if ($this->verbose || empty($this->numberOfTests)) {
510 array_push($this->numberOfTests, 0);
511 array_push($this->testSuiteSize, count($suite));
514 $this->lastEvent = self::EVENT_TESTSUITE_START;
520 * @param PHPUnit_Framework_TestSuite $suite
521 * @since Method available since Release 2.2.0
523 public function endTestSuite(PHPUnit_Framework_TestSuite $suite)
525 if ($this->verbose) {
526 array_pop($this->numberOfTests);
527 array_pop($this->testSuiteSize);
531 if ($this->lastEvent != self::EVENT_TESTSUITE_END) {
536 $this->lastEvent = self::EVENT_TESTSUITE_END;
542 * @param PHPUnit_Framework_Test $test
544 public function startTest(PHPUnit_Framework_Test $test)
546 if ($this->verbose) {
547 $this->numberOfTests[count($this->numberOfTests)-1]++;
550 else if (isset($this->numberOfTests[0])) {
551 $this->numberOfTests[0]++;
555 $this->numberOfTests = array(1);
558 $this->lastEvent = self::EVENT_TEST_START;
563 "\nStarting test '%s'.\n", PHPUnit_Util_Test::describe($test)
572 * @param PHPUnit_Framework_Test $test
575 public function endTest(PHPUnit_Framework_Test $test, $time)
577 if (!$this->lastTestFailed) {
578 $this->writeProgress('.');
581 if ($test instanceof PHPUnit_Framework_TestCase) {
582 $this->numAssertions += $test->getNumAssertions();
585 $this->lastEvent = self::EVENT_TEST_END;
586 $this->lastTestFailed = FALSE;
590 * @param string $progress
592 protected function writeProgress($progress)
594 $indent = max(0, count($this->testSuiteSize) - 1);
596 if ($this->column == 0) {
597 $this->write(str_repeat(' ', $indent));
600 $this->write($progress);
602 if ($this->column++ == 60 - 1 - $indent) {
603 if ($this->verbose) {
604 $numberOfTests = $this->numberOfTests[count($this->numberOfTests)-1];
605 $testSuiteSize = $this->testSuiteSize[count($this->testSuiteSize)-1];
607 $numberOfTests = $this->numberOfTests[0];
608 $testSuiteSize = $this->testSuiteSize[0];
611 $width = strlen((string)$testSuiteSize);
615 ' %' . $width . 'd / %' . $width . "d\n",